package org.ch02.test00.demo10.teacherWork;

import java.lang.reflect.Field;

/**
 * @author CSY
 * @date 2025 - 03 - 24
 */
public class BeanUtil {
    /**
     * 设置何意对象的属性值
     * @param bean 对象
     * @param propertyName 属性名称
     * @param value 值
     */
    public static void setProperty(Object bean, String propertyName, Object value){
        //第一：获取操作类的Class对象
        Class<?> clazz = bean.getClass();

        try {
            //第二：获取Bean对象的字段对象
            Field field = clazz.getDeclaredField(propertyName);

            // 第三：开放访问权限
            field.setAccessible(true);

            //调用setXxx方法，实现初始化工作
            field.set(bean,value);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("未知字段"+e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("初始化字段失败"+e);
        }
    }

    /**
     * 获取任意对象的属性值
     * @param bean
     * @param propertyName
     * @return
     */
    public static Object getProperty(Object bean, String propertyName){
        //第一：获取操作类的Class对象
        Class<?> clazz = bean.getClass();

        try {
            //第二：获取Bean对象的字段对象
            Field field = clazz.getDeclaredField(propertyName);

            // 第三：开放访问权限
            field.setAccessible(true);

            //调用getXxx方法，获取字段数据
            return field.get(bean);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("未知字段"+e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("获取数据失败"+e);
        }
    }

    /**
     * 复制某个对象的属性值到另一个对象中
     * @param sourceBean 源Bean对象
     * @param targetBean 目标Bean对象
     */
    public static void copyProperties(Object sourceBean, Object targetBean){
        //第一：获取要操作类的Class对象
        Class<?> sourceClazz = sourceBean.getClass();
        Class<?> targetClazz = targetBean.getClass();

        //第二：基于Class对象实现相关的操作
        //1.获取源Bean对象的所有字段
        Field[] sourceFields = sourceClazz.getDeclaredFields();

        //2.循环遍历源Bean对象的所有字段
        for (Field sourceField : sourceFields) {
            //设置对象字段权限
            sourceField.setAccessible(true);
            try {
                //3.获取源Bean对象的某个字段数据
                Object sourceFieldData = sourceField.get(sourceBean);
                //根据对象字段名获取到指定字段 - 对象字段名获取 : 由于是克隆所以两个对象字段名一致，直接获取循环的对象的字段名
                Field targetField = targetClazz.getDeclaredField(sourceField.getName());
                targetField.setAccessible(true);
                //设置指定字段的值
                targetField.set(targetBean,sourceFieldData);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
